package org.yihang.util;

import java.io.File;
import java.lang.reflect.Field;

import org.yihang.annotation.Column;
import org.yihang.annotation.Id;
import org.yihang.annotation.Table;

public enum Meta {
	;

	public enum Method {
		SAVE, UPDATE, DELETE_BY, FIND_BY, FIND_ALL, FIND_COUNT, FIND_BY_VO
	}

	public enum Dialect {
		MySQL, ORACLE
	}

	public enum Structure {
		Maven {
			@Override
			public String javaOutputDir(String baseOutputDir, String packageName) {
				StringBuilder sb = new StringBuilder(255);
				sb.append(baseOutputDir);
				sb.append(File.separator);
				sb.append("src");
				sb.append(File.separator);
				sb.append("main");
				sb.append(File.separator);
				sb.append("java");
				sb.append(File.separator);
				sb.append(packageNameToPath(packageName));
				return sb.toString();
			}

			@Override
			public String xmlOutputDir(String baseOutputDir, String packageName) {
				StringBuilder sb = new StringBuilder(255);
				sb.append(baseOutputDir);
				sb.append(File.separator);
				sb.append("src");
				sb.append(File.separator);
				sb.append("main");
				sb.append(File.separator);
				sb.append("resources");
				sb.append(File.separator);
				sb.append(packageNameToPath(packageName));
				return sb.toString();
			}

			@Override
			public String htmlOutputDir(String baseOutputDir, String htmlDir) {
				StringBuilder sb = new StringBuilder(255);
				sb.append(baseOutputDir);
				sb.append(File.separator);
				sb.append("src");
				sb.append(File.separator);
				sb.append("main");
				sb.append(File.separator);
				sb.append("webapp");
				sb.append(File.separator);
				return sb.toString();
			}

		},
		DynamicWebProject {
			@Override
			public String javaOutputDir(String baseOutputDir, String packageName) {
				return dir(baseOutputDir, packageName);
			}

			@Override
			public String xmlOutputDir(String baseOutputDir, String packageName) {
				return dir(baseOutputDir, packageName);
			}

			private String dir(String baseOutputDir, String packageName) {
				StringBuilder sb = new StringBuilder(255);
				sb.append(baseOutputDir);
				sb.append(File.separator);
				sb.append("src");
				sb.append(File.separator);
				sb.append(packageNameToPath(packageName));
				return sb.toString();
			}

			@Override
			public String htmlOutputDir(String baseOutputDir, String htmlDir) {
				StringBuilder sb = new StringBuilder(255);
				sb.append(baseOutputDir);
				sb.append(File.separator);
				sb.append("src");
				sb.append(File.separator);
				sb.append("WebContent");
				sb.append(File.separator);
				return sb.toString();
			}
		};
		private static String packageNameToPath(String packageName) {
			StringBuilder sb = new StringBuilder(255);
			String[] ps = packageName.split("\\.");
			for (String p : ps) {
				sb.append(p).append(File.separator);
			}
			return sb.toString();
		}

		public abstract String javaOutputDir(String baseOutputDir, String packageName);

		public abstract String xmlOutputDir(String baseOutputDir, String packageName);
		
		public abstract String htmlOutputDir(String baseOutputDir, String htmlDir);
	}

	public enum NameStrategy {
		Annotation {

			@Override
			public String tableName(Class<?> c) {
				Table e = c.getAnnotation(Table.class);
				if (e == null) {
					throw new RuntimeException("no @Table found on class[" + c.getName() + "]!");
				}
				if ("".equals(e.value())) {
					return c.getSimpleName();
				}
				return e.value();
			}

			@Override
			public String columnName(Field f) {
				Column c = f.getAnnotation(Column.class);
				Id id = f.getAnnotation(Id.class);
				if (id != null && !"".equals(id.value())) {
					return id.value();
				}
				if (c != null && !"".equals(c.value())) {
					return c.value();
				}
				return f.getName();
			}

			@Override
			public NameStrategy tablePrefix(String prefix) {
				return this;
			}
		},
		CamelUnderscore {
			private String prefix = "t_";

			@Override
			public String tableName(Class<?> c) {
				return prefix + camelToUnderscore(c.getSimpleName());
			}

			@Override
			public String columnName(Field f) {
				return camelToUnderscore(f.getName());
			}

			private String camelToUnderscore(String name) {
				StringBuilder sb = new StringBuilder(name.length() + 4);
				for (int i = 0; i < name.length(); i++) {
					char c = name.charAt(i);
					if (i == 0) {
						sb.append(Character.toLowerCase(c));
					} else if (Character.isUpperCase(c)) {
						sb.append("_").append(Character.toLowerCase(c));
					} else {
						sb.append(c);
					}
				}
				return sb.toString();
			}

			@Override
			public NameStrategy tablePrefix(String prefix) {
				this.prefix = prefix;
				return this;
			}
		};

		public abstract String tableName(Class<?> c);

		public abstract String columnName(Field f);

		public abstract NameStrategy tablePrefix(String prefix);
	}

}
